package com.puccampinas.finalproject.core.logs;

import java.util.concurrent.ConcurrentHashMap;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

import com.puccampinas.finalproject.core.logs.LoggerType;

/**
 * @author Fernando H. S. Goncalves <mailto:fernando.goncalves@movile.com>
 */

public class LogUtils {
	
	private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
	
	private static ConcurrentHashMap<LoggerType, Logger> loggers = new ConcurrentHashMap<LoggerType, Logger>();
	
	private static Boolean logCallerInfo = Boolean.TRUE;
	
	
	public static void init (String pathXmlConfig, Boolean logCallerInfo) throws Exception {
		
		LogUtils.logCallerInfo = logCallerInfo;
		
		DOMConfigurator.configure(pathXmlConfig);
		
		for (LoggerType logger : LoggerType.values()) {
			loggers.put(logger, Logger.getLogger(logger.toString()));
		}
	}
	
	
	public static String get () {

		return threadLocal.get();
	}

	public static void stamp () {
			
		StringBuilder id = new StringBuilder();

		id.append(System.currentTimeMillis());
		id.append(UUID.randomUUID().toString().replaceAll("\\-.*$", ""));

		threadLocal.set(id.toString());
	}
	
	public static void clear () {
		
		if (threadLocal.get() != null) {
			threadLocal.remove();
		}
	}
	
	
	private static String getCallTrace (int depth) {

		String callTrace = null;
		
		StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
		
		if (depth >= 0 && callStack.length > depth+2) {
			
			StackTraceElement st = callStack[depth+2];
			callTrace = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber() +")]";
		}
		
		return callTrace;
	}

	
	public static void debug (LoggerType loggerType, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).debug(sbLog.toString());
	}
	
	public static void debug (Logger logger, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.debug(sbLog.toString());
	}	
	
	public static void debug (LoggerType loggerType, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).debug(sbLog.toString(), e);
	}
	
	public static void debug (Logger logger, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.debug(sbLog.toString(), e);
	}	
	
	
	public static void error (LoggerType loggerType, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).error(sbLog.toString());
	}
	
	public static void error (Logger logger, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.error(sbLog.toString());
	}
	
	public static void error (LoggerType loggerType, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).error(sbLog.toString(), e);
	}

	public static void error (Logger logger, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.error(sbLog.toString(), e);
	}
	
		
	public static void fatal (LoggerType loggerType, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).fatal(sbLog.toString());
	}
	
	public static void fatal (Logger logger, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.fatal(sbLog.toString());
	}
	
	public static void fatal (LoggerType loggerType, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).fatal(sbLog.toString(), e);
	}
	
	public static void fatal (Logger logger, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.fatal(sbLog.toString(), e);
	}
	
	
	public static void info (LoggerType loggerType, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).info(sbLog.toString());
	}
	
	public static void info (Logger logger, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.info(sbLog.toString());
	}
	
	public static void info (LoggerType loggerType, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).info(sbLog.toString(), e);
	}

	public static void info (Logger logger, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.info(sbLog.toString(), e);
	}
	
	
	public static void warn (LoggerType loggerType, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).warn(sbLog.toString());
	}
	
	public static void warn (Logger logger, String message) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.warn(sbLog.toString());
	}
	
	public static void warn (LoggerType loggerType, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		loggers.get(loggerType).warn(sbLog.toString(), e);
	}
	
	public static void warn (Logger logger, String message, Throwable e) {
		
		StringBuilder sbLog = new StringBuilder();
		
		if (logCallerInfo) {
			String callTrace = getCallTrace(1);
			sbLog.append(callTrace);
		}
		
		if (get() != null) {
			sbLog.append("[").append(get()).append("]");
		}
		
		sbLog.append(" ").append(message);
		
		logger.warn(sbLog.toString(), e);
	}
	
}
